
import { GroupCluster, newGroup } from "./cluster";

import { GroupWorkers } from "../terminal/workers";
import { getHostiles, mapRoomDomain } from "../../../global/map";
import { ClusterDefenders } from "./defenders";
import { ClusterExplorers } from "./explorers";
import { errLog } from "../../../util/log";
import { getCreepActivityCoeficient, getMaxEnergy, getMinEnergy } from "../../../role/spawn";
import { ClusterStructure } from "./structure";

export class ClusterIndependent extends GroupCluster{
    constructor(spawnRoom=undefined){
        super(spawnRoom);
        if(spawnRoom!=undefined){
            this.init(spawnRoom);
        }
    }
    get maxSize(){
        let ans = 0;
        ans+=this.workerGroup.maxSize;
        if(this.isPanicing()){
            ans+=this.defenderGroup.maxSize;
        }else{
            ans++;
        }
        ans+=this.explorerGroup.maxSize;
        // console.log(ans);
        return ans;
    }
    get size(){
        return this.workerGroup.size+this.defenderGroup.size+this.explorerGroup.size;
    }
    init(spawnRoom){
        mapRoomDomain(spawnRoom);
        this.workerGroup = new GroupWorkers(spawnRoom);
        this.defenderGroup = new ClusterDefenders(spawnRoom);
        this.explorerGroup = new ClusterExplorers(spawnRoom);
        this.structureGroup = new ClusterStructure(spawnRoom);
    }
    serialize(){
        return {
            cluster: super.serialize(), 
            workerGroup: this.workerGroup.serialize(),
            defenderGroup: this.defenderGroup.serialize(),
            explorerGroup: this.explorerGroup.serialize(),
            structureGroup: this.structureGroup.serialize(),
        };
    }
    deserialize(obj){
        super.deserialize(obj.cluster);
        this.workerGroup = newGroup(GroupWorkers, obj.workerGroup, this.spawnRoom);
        this.defenderGroup = newGroup(ClusterDefenders, obj.defenderGroup, this.spawnRoom);
        this.explorerGroup = newGroup(ClusterExplorers, obj.explorerGroup, this.spawnRoom);
        this.structureGroup = newGroup(ClusterStructure, obj.structureGroup, this.spawnRoom);

        this.spawnRoom.maxCreepCount = this.maxSize;
        return this;
    }
    isPanicing(){
        let targets = getHostiles(this.spawnRoom,false);
        if(targets.length===0){
            return false;
        }
        for(let target of targets){
            if(target.room.name === this.spawnRoomName){
                return true;
            }
        }
        return false;
    }
    normalSpawn(){
        if(this.workerGroup.size/this.workerGroup.maxSize<0.3){
            return this.workerGroup.spawn();
        }
        if(getMinEnergy(this.spawnRoom)/getMaxEnergy(this.spawnRoom)>0.5){
            let ret = this.explorerGroup.spawn();
            if(ret === OK){
                return ret;
            }
        }
        if(this.workerGroup.size/this.workerGroup.maxSize<0.5){
            return this.workerGroup.spawn();
        }
        if(this.defenderGroup.size === 0 && getCreepActivityCoeficient(this.spawnRoom, false)>0.9){
            return this.defenderGroup.spawn();
        }
        if(this.workerGroup.size<this.workerGroup.maxSize){
            return this.workerGroup.spawn();
        }
        if(this.explorerGroup.size<this.explorerGroup.maxSize){
            if(this.explorerGroup.spawn() === OK){
                return OK;
            }
        }
        return ERR_FULL;
    }
    panicSpawn(){
        if(this.workerGroup.size/this.workerGroup.maxSize<0.4){
            return this.workerGroup.spawn();
        }

        if(this.defenderGroup.size/this.defenderGroup.maxSize<this.workerGroup.size/this.workerGroup.maxSize){
            return this.defenderGroup.spawn();
        }

        if(this.workerGroup.size<this.workerGroup.maxSize){
            return this.workerGroup.spawn();
        }
        if(this.explorerGroup.size<this.explorerGroup.maxSize){
            return this.explorerGroup.spawn();
        }
        if(this.defenderGroup.size<this.defenderGroup.maxSize){
            return this.defenderGroup.spawn();
        }

        return ERR_FULL;
    }
    spawn(){
        let ret;
        if(this.isPanicing()){
            ret = this.panicSpawn();
        }else{
            ret = this.normalSpawn();
        }
        return ret;
    }
    run(){
        try{
            this.explorerGroup.run();
        }catch(e){
            errLog(e);
        }
        try{
            this.defenderGroup.run();
        }catch(e){
            errLog(e);
        }
        try{
            this.workerGroup.run();
        }catch(e){
            errLog(e);
        }

        try{
            this.structureGroup.run();
        }catch(e){
            errLog(e);
        }

        return OK;
    }
    
}